﻿// Copyright (c) 2011, Adaptiv Design
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//    * Neither the name of the <ORGANIZATION> nor the names of its contributors may
// be used to endorse or promote products derived from this software without specific
// prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using Alicanto.Lexing;

namespace Alicanto.Compilation.Code
{
    /// <summary>
    /// 
    /// </summary>
    internal interface ICodeGenerator
    {
        Expression Code { get; }
        IEnumerable<ParseInstruction> Generate(TokenSequence tokens, Scope scope);
    }

    /// <summary>
    /// Complements the ICodeGenerator interface. Tells the parser to generate the code at the end of it's containing scope.
    /// </summary>
    internal interface IRequiresDelayedParsing
    {
        TokenSequence SkipTokens(TokenSequence tokens);
    }

    /// <summary>
    /// Base class for every parse instruction
    /// </summary>
    internal abstract class ParseInstruction { }

    /// <summary>
    /// Tells the parser to parse the next sequence of tokens as a new expression.
    /// This will ensure that operator presedence is applied.
    /// </summary>
    internal class ParseExpression : ParseInstruction
    {
        internal Expression Expression { get; set; }
    }

    /// <summary>
    /// Parses the remainder of the current expression.
    /// </summary>
    internal class ParseExpressionRemainder : ParseInstruction
    {
        internal Expression Remainder { get; set; }
    }

    /// <summary>
    /// Parses untill end of file or end of block.
    /// </summary>
    internal class Parse : ParseInstruction
    {
        internal IList<Expression> Expressions { get; set; }
    }

    /// <summary>
    /// Parses a single block until the end of that block.
    /// </summary>
    internal class ParseBlock : ParseInstruction
    {
        internal Expression Block { get; set; }
    }

    /// <summary>
    /// Parses a sequence of expressions.
    /// </summary>
    internal class ParseSequence : ParseInstruction
    {
        internal Token TokenOpen { get; private set; }
        internal Token TokenClose { get; private set; }

        internal ParseSequence(Token tokenOpen, Token tokenClose)
        {
            this.TokenOpen = tokenOpen;
            this.TokenClose = tokenClose;
        }

        internal IList<Expression> Expressions { get; set; }
    }

    /// <summary>
    /// Returns the current evaluation.
    /// </summary>
    internal class GetEvaluation : ParseInstruction
    {
        internal Expression Expression { get; set; }
    }

    /// <summary>
    ///
    /// </summary>
    internal class GenerateNextTokenWith : ParseInstruction
    {
        internal ICodeGenerator Generator { get; private set; }
        internal GenerateNextTokenWith(ICodeGenerator generator)
        {
            this.Generator = generator;
        }
    }

    /// <summary>
    /// Enters a new scope.
    /// </summary>
    internal class EnterScope : ParseInstruction
    {
        internal Scope Scope { get; set; }
    }

    /// <summary>
    /// Leaves the current scope.
    /// </summary>
    internal class LeaveScope : ParseInstruction
    {
        internal Expression Finalizer { get; set; }
    }

    /// <summary>
    /// Omits the code currently generated.
    /// </summary>
    internal class OmitCode : ParseInstruction
    {

    }
}
